/*
*  This file is part of ygg-brute
*  Copyright (c) 2020 ygg-brute authors
*  See LICENSE for licensing information
*/

#pragma once

#include <list>
#include <optional>
#include <regex>

#include "result.hpp"
#include "stats.hpp"

#include "address.hpp"
#include "generator.hpp"

struct AddressFilter{
    size_t min_hi{0};
    size_t hi{0};
    std::vector<std::regex> re;
};

class Processor {
public:
    struct Ctx {
        std::list<Result> results;
        Stats stats;
    };

    Processor(AddressFilter filter)
    : filter_{std::move(filter)}
    {}

    Ctx process(GeneratorCtx& gen_ctx)
    {
        Ctx ctx;
        ctx.results.emplace_back();

        for(size_t i = 0; i < gen_ctx.batch_size(); ++i) {
            auto& result = ctx.results.back();
            auto* bytes = gen_ctx.address(i);

            auto add_result = [&] {
                memcpy(result.skey, gen_ctx.skey(i), 32);
                ctx.results.emplace_back();
            };

            auto hi = bytes[1];
            ctx.stats.max = std::max<size_t>(ctx.stats.max, hi);
            if(filter_.min_hi && hi < filter_.min_hi) continue;

            if(hi >= filter_.hi) {
                ipv6_to_string(bytes, result.address);
                add_result();
                continue;
            }

            if(filter_.re.size()) {
                ipv6_to_string(bytes, result.address);
                bool matched = false;

                for(auto& re : filter_.re) {
                    if(std::regex_search(result.address, re)) {
                        matched = true;
                        break;
                    }
                }

                if(matched) {
                    add_result();
                    continue;
                }
            }
        }

        ctx.results.pop_back();

        ctx.stats.found = ctx.results.size();
        ctx.stats.processed = gen_ctx.batch_size();

        return ctx;
    }

private:
    AddressFilter filter_;
};